#include <windows.h>
#include "CDXResource.h"
#include "CReleaseMacro.h"
#include <atlcomcli.h>
#include <assert.h>


CDXResource::CDXResource(CDXDevice* pDevice) : CDXBase(pDevice)
{
	m_pD2DRenderTarget = NULL;
	m_hShareHandle = 0;
	m_pDXGISurface10 = NULL;
	m_pDXGISurface11 = NULL;
	m_pKeyMutex10 = NULL;
	m_pKeyMutex11 = NULL;

	m_pDefaultRTV = NULL;
	m_pDefaultSRV = NULL;
	m_pDefaultUAV = NULL;
	m_pDefaultDSV = NULL;
	m_nKeyMutex10LockCount = 0;
	m_nKeyMutex11LockCount = 0;
}

CDXResource::~CDXResource()
{
	ReleaseResources();
}

HRESULT CDXResource::ReleaseResources()
{
	for (UINT i =0; i < m_pRenderTargetView.size();i++)
	{
		SAFE_RELEASE(m_pRenderTargetView[i]);
	}
	m_pRenderTargetView.clear();
	for (UINT i =0; i < m_pShaderResourceView.size();i++)
	{
		SAFE_RELEASE(m_pShaderResourceView[i]);
	}
	m_pShaderResourceView.clear();
	for (UINT i =0; i < m_pUnorderedAccessView.size();i++)
	{
		SAFE_RELEASE(m_pUnorderedAccessView[i]);
	}
	m_pUnorderedAccessView.clear();

	for (std::map<ID2D1RenderTarget*, ID2D1Bitmap*>::iterator iter = m_pD2DBitmap.begin(); iter != m_pD2DBitmap.end(); iter++)
	{
		SAFE_RELEASE(iter->second);
	}
	m_pD2DBitmap.clear();
	for (std::map<ID2D1RenderTarget*, ID2D1BitmapBrush*>::iterator iter = m_pD2DBitmapBrush.begin(); iter != m_pD2DBitmapBrush.end(); iter++)
	{
		SAFE_RELEASE(iter->second);
	}
	m_pD2DBitmapBrush.clear();

	
	SAFE_RELEASE(m_pD2DRenderTarget);

	SAFE_RELEASE(m_pDXGISurface10);
	SAFE_RELEASE(m_pDXGISurface11);
	SAFE_RELEASE(m_pKeyMutex10);
	SAFE_RELEASE(m_pKeyMutex11);
	SAFE_RELEASE(m_pDefaultSRV);
	SAFE_RELEASE(m_pDefaultRTV);
	SAFE_RELEASE(m_pDefaultUAV);
	SAFE_RELEASE(m_pDefaultDSV);

	m_hShareHandle = 0;
	return S_OK;
}

HRESULT CDXResource::GetRenderTargetView(D3D11_RENDER_TARGET_VIEW_DESC* pDesc, ID3D11RenderTargetView** ppRenderTargetView)
{
	if (m_pDevice == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	if (pDesc == NULL)
	{
		if (m_pDefaultRTV == NULL)
		{
			ID3D11Resource* pResource = this->GetResource();
			if (pResource == NULL)
				return E_FAIL;
			ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
			hr = pDX11Device->CreateRenderTargetView(pResource, NULL, &m_pDefaultRTV);
			if (FAILED(hr))
				return hr;
		}
		*ppRenderTargetView = m_pDefaultRTV;
		return hr;
	}
	D3D11_RENDER_TARGET_VIEW_DESC checkDesc;
	for (UINT i =0; i < m_pRenderTargetView.size(); i++)
	{
		m_pRenderTargetView[i]->GetDesc(&checkDesc);
		
		if (IsEqual(checkDesc,*pDesc))
		{
			SAFE_RELEASE(*ppRenderTargetView);
			*ppRenderTargetView = m_pRenderTargetView[i];
			return S_OK;
		}
	}

	ID3D11Resource* pResource = this->GetResource();
	if (pResource == NULL)
		return E_FAIL;
	ID3D11RenderTargetView* pRTV = NULL;
	ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
	hr = pDX11Device->CreateRenderTargetView(pResource, pDesc, &pRTV);
	if (FAILED(hr))
		return hr;
	m_pRenderTargetView.push_back(pRTV);

	*ppRenderTargetView = pRTV;
	return S_OK;
}
HRESULT CDXResource::GetShaderResourceView(D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,ID3D11ShaderResourceView** ppShaderResourceView)
{
	if (m_pDevice == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	if (pDesc == NULL)
	{
		if (m_pDefaultSRV == NULL)
		{
			ID3D11Resource* pResource = this->GetResource();
			if (pResource == NULL)
				return E_FAIL;
			ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
			hr = pDX11Device->CreateShaderResourceView(pResource, NULL, &m_pDefaultSRV);
			if (FAILED(hr))
				return hr;
		}
		*ppShaderResourceView = m_pDefaultSRV;
		return hr;
	}
	D3D11_SHADER_RESOURCE_VIEW_DESC checkDesc;
	for (UINT i =0; i < m_pShaderResourceView.size(); i++)
	{
		m_pShaderResourceView[i]->GetDesc(&checkDesc);
		if (IsEqual(checkDesc, *pDesc))
		{
			SAFE_RELEASE(*ppShaderResourceView);
			*ppShaderResourceView = m_pShaderResourceView[i];
			return S_OK;
		}
	}

	ID3D11Resource* pResource = this->GetResource();
	if (pResource == NULL)
		return E_FAIL;
	ID3D11ShaderResourceView* pSRV = NULL;
	ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
	hr = pDX11Device->CreateShaderResourceView(pResource, pDesc, &pSRV);
	if (FAILED(hr))
		return hr;
	m_pShaderResourceView.push_back(pSRV);

	*ppShaderResourceView = pSRV;
	return S_OK;
}
HRESULT CDXResource::GetUnorderedAccessView(D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc, ID3D11UnorderedAccessView** ppUnorderedAccessView)
{
	if (m_pDevice == NULL )
		return E_FAIL;
	HRESULT hr = S_OK;
	if (pDesc == NULL)
	{
		if (m_pDefaultUAV == NULL)
		{
			ID3D11Resource* pResource = this->GetResource();
			if (pResource == NULL)
				return E_FAIL;
			ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
			hr = pDX11Device->CreateUnorderedAccessView(pResource, NULL, &m_pDefaultUAV);
			if (FAILED(hr))
				return hr;
		}
		*ppUnorderedAccessView = m_pDefaultUAV;
		return hr;
	}
	D3D11_UNORDERED_ACCESS_VIEW_DESC checkDesc;
	for (UINT i =0; i < m_pUnorderedAccessView.size(); i++)
	{
		m_pUnorderedAccessView[i]->GetDesc(&checkDesc);
		if (IsEqual(checkDesc, *pDesc))
		{
			SAFE_RELEASE(*ppUnorderedAccessView);
			*ppUnorderedAccessView = m_pUnorderedAccessView[i];
			return S_OK;
		}
	}

	ID3D11Resource* pResource = this->GetResource();
	if (pResource == NULL)
		return E_FAIL;
	ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
	ID3D11UnorderedAccessView* pUAV = NULL;
	hr = pDX11Device->CreateUnorderedAccessView(pResource, pDesc, &pUAV);
	if (FAILED(hr))
		return hr;
	m_pUnorderedAccessView.push_back(pUAV);

	*ppUnorderedAccessView = pUAV;
	return S_OK;
}
HRESULT CDXResource::GetDepthStencilView(D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc, ID3D11DepthStencilView** ppDepthStencilView)
{
	if (m_pDevice == NULL )
		return E_FAIL;
	HRESULT hr = S_OK;
	if (pDesc == NULL)
	{
		if (m_pDefaultDSV == NULL)
		{
			ID3D11Resource* pResource = this->GetResource();
			if (pResource == NULL)
				return E_FAIL;
			ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
			hr = pDX11Device->CreateDepthStencilView(pResource, NULL, &m_pDefaultDSV);
			if (FAILED(hr))
				return hr;
		}
		*ppDepthStencilView = m_pDefaultDSV;
		return hr;
	}
	D3D11_DEPTH_STENCIL_VIEW_DESC checkDesc;
	for (UINT i =0; i < m_pDepthStencilView.size(); i++)
	{
		m_pDepthStencilView[i]->GetDesc(&checkDesc);
		if (IsEqual(checkDesc, *pDesc))
		{
			SAFE_RELEASE(*ppDepthStencilView);
			*ppDepthStencilView = m_pDepthStencilView[i];
			return S_OK;
		}
	}

	ID3D11Resource* pResource = this->GetResource();
	if (pResource == NULL)
		return E_FAIL;
	ID3D11DepthStencilView* pDSV = NULL;
	ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
	hr = pDX11Device->CreateDepthStencilView(pResource, pDesc, &pDSV);
	if (FAILED(hr))
		return hr;
	m_pDepthStencilView.push_back(pDSV);

	*ppDepthStencilView = pDSV;
	
	return S_OK;
}
HRESULT CDXResource::GetDXGISurface11(IDXGISurface1** ppDXGISurface)
{
	ID3D11Resource* pResource = GetResource();
	if (pResource == NULL)
		return E_FAIL;

	HRESULT hr = S_OK;
	if (m_pDXGISurface11 == NULL)
	{
		hr = pResource->QueryInterface(&m_pDXGISurface11);
		if (FAILED(hr))
			return hr;
	}
	*ppDXGISurface = m_pDXGISurface11;
	return S_OK;
}
HRESULT CDXResource::GetDXGISurface10(IDXGISurface1** ppDXGISurface)
{
	ID3D11Resource* pResource = GetResource();
	if (pResource == NULL)
		return E_FAIL;

	HRESULT hr = S_OK;
	if (m_pDXGISurface10 == NULL)
	{
		if (m_pDevice == NULL)
			return E_FAIL;

		ID3D10Device* pD3D10Device = NULL;
		hr = m_pDevice->GetD3D10Device(&pD3D10Device);
		if (FAILED(hr))
			return hr;

		HANDLE hResource = 0;
		hr = GetShareHandle(hResource);
		if (FAILED(hr) || hResource == 0)
		{
			assert(0);
			return hr;
		}
		IDXGISurface1* pDXGISurface10 = NULL;	
		hr = pD3D10Device->OpenSharedResource(hResource, __uuidof(IDXGISurface1), (void**)&pDXGISurface10);
		if (FAILED(hr))
		{
			assert(0);
			return hr;
		}
		m_pDXGISurface10 = pDXGISurface10;
	}
	*ppDXGISurface = m_pDXGISurface10;
	return S_OK;
}

HRESULT CDXResource::GetKeyMutex11(IDXGIKeyedMutex** ppKeyMutex)
{
	HRESULT hr = S_OK;
	if (m_pKeyMutex11 == NULL)
	{
		IDXGISurface1* pDXGISurface = NULL;
		hr = GetDXGISurface11(&pDXGISurface);
		if (FAILED(hr))
			return hr;
		hr = pDXGISurface->QueryInterface(&m_pKeyMutex11);
		if (FAILED(hr))
			return hr;
	}
	*ppKeyMutex = m_pKeyMutex11;
	return S_OK;
}

HRESULT CDXResource::GetKeyMutex10(IDXGIKeyedMutex** ppKeyMutex)
{
	HRESULT hr = S_OK;
	if (m_pKeyMutex10 == NULL)
	{
		IDXGISurface1* pDXGISurface = NULL;
		hr = GetDXGISurface10(&pDXGISurface);
		if (FAILED(hr))
			return hr;
		hr = pDXGISurface->QueryInterface(&m_pKeyMutex10);
		if (FAILED(hr))
			return hr;
	}
	*ppKeyMutex = m_pKeyMutex10;
	return S_OK;
}
BOOL CDXResource::IsKeyMutexShared()
{
	return FALSE;
}
HRESULT CDXResource::KeyMutex11Acquire()
{
	if (!IsKeyMutexShared())
	{
		return S_FALSE;
	}

	HRESULT hr = S_OK;
	IDXGIKeyedMutex* pKeyMutex = NULL;
	hr = GetKeyMutex11(&pKeyMutex);
	if (FAILED(hr))
		return hr;
	ULONG cnt = InterlockedIncrement(&m_nKeyMutex11LockCount);
	if (cnt == 1)
	{
		hr = pKeyMutex->AcquireSync(0, INFINITE);
	}
	return hr;
}

HRESULT CDXResource::KeyMutex11Release()
{
	if (!IsKeyMutexShared())
	{
		return S_FALSE;
	}
	HRESULT hr = S_OK;
	IDXGIKeyedMutex* pKeyMutex = NULL;
	hr = GetKeyMutex11(&pKeyMutex);
	if (FAILED(hr))
		return hr;
	ULONG cnt = InterlockedDecrement(&m_nKeyMutex11LockCount);
	if (cnt == 0)
	{
		hr = pKeyMutex->ReleaseSync(0);
	}
	else if (cnt < 0)
	{
		assert(0);
		return E_FAIL;
	}
	return hr;
}

HRESULT CDXResource::KeyMutex10Acquire()
{
	if (!IsKeyMutexShared())
	{
		return S_FALSE;
	}
	HRESULT hr = S_OK;
	IDXGIKeyedMutex* pKeyMutex = NULL;
	hr = GetKeyMutex10(&pKeyMutex);
	if (FAILED(hr))
		return hr;
	ULONG cnt = InterlockedIncrement(&m_nKeyMutex10LockCount);
	if (cnt == 1)
	{
		hr = pKeyMutex->AcquireSync(0, INFINITE);
	}
	return hr;
}

HRESULT CDXResource::KeyMutex10Release()
{
	if (!IsKeyMutexShared())
	{
		return S_FALSE;
	}
	HRESULT hr = S_OK;
	IDXGIKeyedMutex* pKeyMutex = NULL;
	hr = GetKeyMutex10(&pKeyMutex);
	if (FAILED(hr))
		return hr;
	ULONG cnt = InterlockedDecrement(&m_nKeyMutex10LockCount);
	if (cnt == 0)
	{
		hr = pKeyMutex->ReleaseSync(0);
	}
	return hr;
}
BOOL CDXResource::IsEqual(const D3D11_RENDER_TARGET_VIEW_DESC& desc1, const D3D11_RENDER_TARGET_VIEW_DESC& desc2)
{
	if (desc1.Format != desc2.Format || desc1.ViewDimension != desc2.ViewDimension )
		return false;
	bool ret = false;
	switch (desc1.ViewDimension)
	{
	case D3D11_RTV_DIMENSION_UNKNOWN:
		ret = (memcmp(&desc1, &desc2, sizeof(D3D11_RENDER_TARGET_VIEW_DESC)) == 0);
		break;
	case D3D11_RTV_DIMENSION_BUFFER:
		ret = memcmp(&desc1.Buffer, &desc2.Buffer, sizeof(D3D11_BUFFER_RTV)) == 0;
		break;
	case D3D11_RTV_DIMENSION_TEXTURE1D:
		ret = memcmp(&desc1.Texture1D, &desc2.Texture1D, sizeof(D3D11_TEX1D_RTV)) == 0;
		break;
	case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
		ret = memcmp(&desc1.Texture1DArray, &desc2.Texture1DArray, sizeof(D3D11_TEX1D_ARRAY_RTV)) == 0;
		break;
	case D3D11_RTV_DIMENSION_TEXTURE2D:
		ret = memcmp(&desc1.Texture2D, &desc2.Texture2D, sizeof(D3D11_TEX2D_RTV)) == 0;
		break;
	case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
		ret = memcmp(&desc1.Texture2DArray, &desc2.Texture2DArray, sizeof(D3D11_TEX2D_ARRAY_RTV)) == 0;
		break;
	case D3D11_RTV_DIMENSION_TEXTURE2DMS:
		ret = memcmp(&desc1.Texture2DMS, &desc2.Texture2DMS, sizeof(D3D11_TEX2DMS_RTV)) == 0;
		break;
	case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
		ret = memcmp(&desc1.Texture2DMSArray, &desc2.Texture2DMSArray, sizeof(D3D11_TEX2DMS_ARRAY_RTV)) == 0;
		break;
	case D3D11_RTV_DIMENSION_TEXTURE3D:
		ret = memcmp(&desc1.Texture3D, &desc2.Texture3D, sizeof(D3D11_TEX3D_RTV)) == 0;
		break;
	default:
		break;
	}
	return ret;
}
BOOL CDXResource::IsEqual(const D3D11_SHADER_RESOURCE_VIEW_DESC& desc1, const D3D11_SHADER_RESOURCE_VIEW_DESC& desc2)
{
	if (desc1.Format != desc2.Format || desc1.ViewDimension != desc2.ViewDimension )
		return false;
	bool ret = false;
	switch (desc1.ViewDimension)
	{
	case D3D11_SRV_DIMENSION_UNKNOWN:
		ret = (memcmp(&desc1, &desc2, sizeof(D3D11_RENDER_TARGET_VIEW_DESC)) == 0);
		break;
	case D3D11_SRV_DIMENSION_BUFFER:
		ret = memcmp(&desc1.Buffer, &desc2.Buffer, sizeof(D3D11_BUFFER_SRV)) == 0;
		break;
	case D3D11_SRV_DIMENSION_TEXTURE1D:
		ret = memcmp(&desc1.Texture1D, &desc2.Texture1D, sizeof(D3D11_TEX1D_SRV)) == 0;
		break;
	case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
		ret = memcmp(&desc1.Texture1DArray, &desc2.Texture1DArray, sizeof(D3D11_TEX1D_ARRAY_SRV)) == 0;
		break;
	case D3D11_SRV_DIMENSION_TEXTURE2D:
		ret = memcmp(&desc1.Texture2D, &desc2.Texture2D, sizeof(D3D11_TEX2D_SRV)) == 0;
		break;
	case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
		ret = memcmp(&desc1.Texture2DArray, &desc2.Texture2DArray, sizeof(D3D11_TEX2D_ARRAY_SRV)) == 0;
		break;
	case D3D11_SRV_DIMENSION_TEXTURE2DMS:
		ret = memcmp(&desc1.Texture2DMS, &desc2.Texture2DMS, sizeof(D3D11_TEX2DMS_SRV)) == 0;
		break;
	case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
		ret = memcmp(&desc1.Texture2DMSArray, &desc2.Texture2DMSArray, sizeof(D3D11_TEX2DMS_ARRAY_SRV)) == 0;
		break;
	case D3D11_SRV_DIMENSION_TEXTURE3D:
		ret = memcmp(&desc1.Texture3D, &desc2.Texture3D, sizeof(D3D11_TEX3D_SRV)) == 0;
		break;
	case D3D11_SRV_DIMENSION_TEXTURECUBE:
		ret = memcmp(&desc1.TextureCube, &desc2.TextureCube, sizeof(D3D11_TEXCUBE_SRV)) == 0;
		break;
	case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY:
		ret = memcmp(&desc1.TextureCubeArray, &desc2.TextureCubeArray, sizeof(D3D11_TEXCUBE_ARRAY_SRV)) == 0;
		break;
	case D3D11_SRV_DIMENSION_BUFFEREX:
		ret = memcmp(&desc1.BufferEx, &desc2.BufferEx, sizeof(D3D11_BUFFER_SRV)) == 0;
		break;
	default:
		break;
	}
	return true;
}
BOOL CDXResource::IsEqual(const D3D11_UNORDERED_ACCESS_VIEW_DESC& desc1, const D3D11_UNORDERED_ACCESS_VIEW_DESC& desc2)
{
	if (desc1.Format != desc2.Format || desc1.ViewDimension != desc2.ViewDimension)
		return false;
	bool ret = false;
	switch (desc1.ViewDimension)
	{
	case D3D11_UAV_DIMENSION_UNKNOWN:
		ret = (memcmp(&desc1, &desc2, sizeof(D3D11_RENDER_TARGET_VIEW_DESC)) == 0);
		break;
	case D3D11_UAV_DIMENSION_BUFFER:
		ret = memcmp(&desc1.Buffer, &desc2.Buffer, sizeof(D3D11_BUFFER_UAV)) == 0;
		break;
	case D3D11_UAV_DIMENSION_TEXTURE1D:
		ret = memcmp(&desc1.Texture1D, &desc2.Texture1D, sizeof(D3D11_TEX1D_UAV)) == 0;
		break;
	case D3D11_UAV_DIMENSION_TEXTURE1DARRAY:
		ret = memcmp(&desc1.Texture1DArray, &desc2.Texture1DArray, sizeof(D3D11_TEX1D_ARRAY_UAV)) == 0;
		break;
	case D3D11_UAV_DIMENSION_TEXTURE2D:
		ret = memcmp(&desc1.Texture2D, &desc2.Texture2D, sizeof(D3D11_TEX2D_UAV)) == 0;
		break;
	case D3D11_UAV_DIMENSION_TEXTURE2DARRAY:
		ret = memcmp(&desc1.Texture2DArray, &desc2.Texture2DArray, sizeof(D3D11_TEX2D_ARRAY_UAV)) == 0;
		break;
	case D3D11_UAV_DIMENSION_TEXTURE3D:
		ret = memcmp(&desc1.Texture3D, &desc2.Texture3D, sizeof(D3D11_TEX3D_UAV)) == 0;
		break;
	default:
		break;
	}
	return ret;

}
BOOL CDXResource::IsEqual(const D3D11_DEPTH_STENCIL_VIEW_DESC& desc1, const D3D11_DEPTH_STENCIL_VIEW_DESC& desc2)
{
	if (desc1.Format != desc2.Format || desc1.ViewDimension != desc2.ViewDimension || desc1.Flags != desc2.Flags)
		return false;
	bool ret = false;
	switch (desc1.ViewDimension)
	{
	case D3D11_DSV_DIMENSION_UNKNOWN:
		ret = (memcmp(&desc1, &desc2, sizeof(D3D11_RENDER_TARGET_VIEW_DESC)) == 0);
		break;
	case D3D11_DSV_DIMENSION_TEXTURE1D:
		ret = memcmp(&desc1.Texture1D, &desc2.Texture1D, sizeof(D3D11_TEX1D_DSV)) == 0;
		break;
	case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
		ret = memcmp(&desc1.Texture1DArray, &desc2.Texture1DArray, sizeof(D3D11_TEX1D_ARRAY_DSV)) == 0;
		break;
	case D3D11_DSV_DIMENSION_TEXTURE2D:
		ret = memcmp(&desc1.Texture2D, &desc2.Texture2D, sizeof(D3D11_TEX2D_DSV)) == 0;
		break;
	case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
		ret = memcmp(&desc1.Texture2DArray, &desc2.Texture2DArray, sizeof(D3D11_TEX2D_ARRAY_DSV)) == 0;
		break;
	case D3D11_DSV_DIMENSION_TEXTURE2DMS:
		ret = memcmp(&desc1.Texture2DMS, &desc2.Texture2DMS, sizeof(D3D11_TEX2DMS_DSV)) == 0;
		break;
	case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
		ret = memcmp(&desc1.Texture2DMSArray, &desc2.Texture2DMSArray, sizeof(D3D11_TEX2DMS_ARRAY_DSV)) == 0;
		break;
	
	default:
		break;
	}
	
	return true;
}


HRESULT CDXResource::GetShareHandle(HANDLE& hResource)
{
	ID3D11Resource* pResource = GetResource();
	if (pResource == NULL)
		return E_FAIL;

	if (m_hShareHandle == 0)
	{
		HRESULT hr = S_OK;
		IDXGIResource* pdxgiResource = NULL;
		hr = pResource->QueryInterface(&pdxgiResource);
		if (FAILED(hr))
			return hr;

		hr = pdxgiResource->GetSharedHandle(&m_hShareHandle);
		if (FAILED(hr) || m_hShareHandle == 0)
		{
			SAFE_RELEASE(pdxgiResource);
			assert(0);
			return hr;
		}
		SAFE_RELEASE(pdxgiResource);
	}
	hResource = m_hShareHandle;
	return S_OK;
}
HRESULT CDXResource::OpenShareHandle(HANDLE hResource)
{
	return E_NOTIMPL;
}

HRESULT CDXResource::CopyFrom(const CDXResource* pResource)
{
	if (pResource == NULL || m_pDevice == NULL)
		return E_INVALIDARG;
	ID3D11Resource* pDstResource = GetResource();
	ID3D11Resource* pSrcResource = pResource->GetResource();
	if (pDstResource == NULL || pSrcResource == NULL)
		return E_FAIL;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	pContext->CopyResource(pDstResource, pSrcResource);
	return S_OK;
}
HRESULT CDXResource::CopySubresourceRegion(UINT DstSubresource, UINT DstX, UINT DstY, UINT DstZ, CDXResource* pSrcGSResource, 
											UINT SrcSubresource, const D3D11_BOX *pSrcBox)
{
	if (pSrcGSResource == NULL || m_pDevice == NULL)	
		return E_INVALIDARG;
	ID3D11Resource* pDstResource = GetResource();
	ID3D11Resource* pSrcResource = pSrcGSResource->GetResource();
	if (pDstResource == NULL || pSrcResource == NULL)
		return E_FAIL;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	pContext->CopySubresourceRegion(pDstResource, DstSubresource, DstX, DstY, DstZ, 
		pSrcResource, SrcSubresource, pSrcBox);
	return S_OK;
}
HRESULT CDXResource::GetD2DRenderTarget(ID2D1RenderTarget** ppD2DRenderTarget)
{
	ID3D11Resource* pResource = GetResource();
	if (pResource == NULL)
		return E_FAIL;

	HRESULT hr = S_OK;
	if (m_pD2DRenderTarget == NULL)
	{
		ID2D1Factory* pD2DFactory = NULL;
		hr = m_pDevice->GetD2DFactory(&pD2DFactory);
		if (pD2DFactory == NULL)
			return E_FAIL;

		IDXGISurface1* pDXGISurface = NULL;
		hr = GetDXGISurface10(&pDXGISurface);
		if (pDXGISurface == NULL)
			return E_FAIL;

		FLOAT dpiX;
		FLOAT dpiY;
		pD2DFactory->GetDesktopDpi(&dpiX, &dpiY);

		D2D1_RENDER_TARGET_PROPERTIES props =
			D2D1::RenderTargetProperties(
			D2D1_RENDER_TARGET_TYPE_HARDWARE,
			D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED ),
			dpiX,
			dpiY
			);

		hr = pD2DFactory->CreateDxgiSurfaceRenderTarget(pDXGISurface, props, &m_pD2DRenderTarget);
		if (FAILED(hr))
		{
			return hr;
		}
	}
	*ppD2DRenderTarget = m_pD2DRenderTarget;

	return S_OK;
}
HRESULT CDXResource::GetD2DBitmap(ID2D1RenderTarget* pD2DRenderTarget, ID2D1Bitmap** ppD2DBitmap)
{
	HRESULT hr = S_OK;
	if (pD2DRenderTarget == NULL)
	{
		hr = GetD2DRenderTarget(&pD2DRenderTarget);
		if (FAILED(hr))
			return hr;
	}
	std::map<ID2D1RenderTarget*, ID2D1Bitmap*>::iterator iter;
	iter = m_pD2DBitmap.find(pD2DRenderTarget);
	if (iter == m_pD2DBitmap.end())
	{
		IDXGISurface1* pDXGISurface10 = NULL;
		hr = GetDXGISurface10(&pDXGISurface10);
		if (FAILED(hr))
			return hr;
		float dpiX = 96;
		float dpiY = 96;
		pD2DRenderTarget->GetDpi(&dpiX, &dpiY);
		D2D1_PIXEL_FORMAT fmt = pD2DRenderTarget->GetPixelFormat();
		D2D1_BITMAP_PROPERTIES prop;
		prop.pixelFormat = fmt;
		prop.dpiX = dpiX;
		prop.dpiY = dpiY;
		ID2D1Bitmap* pD2DBitmap = NULL;
		KeyMutex10Acquire();
		hr = pD2DRenderTarget->CreateSharedBitmap(__uuidof(IDXGISurface), (void*)pDXGISurface10, &prop, &pD2DBitmap);
		KeyMutex10Release();
		if (FAILED(hr))
			return hr;
		m_pD2DBitmap[pD2DRenderTarget] = pD2DBitmap;
	}
	*ppD2DBitmap = m_pD2DBitmap[pD2DRenderTarget];
	return S_OK;
}
HRESULT CDXResource::GetD2DBitmapBrush(ID2D1RenderTarget* pD2DRenderTarget, ID2D1BitmapBrush** ppBrush)
{
	HRESULT hr = S_OK;
	if (pD2DRenderTarget == NULL)
	{
		hr = GetD2DRenderTarget(&pD2DRenderTarget);
		if (FAILED(hr))
		{
			assert(0);
			return hr;
		}
	}
	std::map<ID2D1RenderTarget*, ID2D1BitmapBrush*>::iterator iter;
	iter = m_pD2DBitmapBrush.find(pD2DRenderTarget);
	if (iter == m_pD2DBitmapBrush.end())
	{
		ID2D1Bitmap* pD2DBitmap = NULL;
		hr = GetD2DBitmap(pD2DRenderTarget, &pD2DBitmap);
		if (FAILED(hr))
			return hr;
		ID2D1BitmapBrush* pD2DBitmapBrush = NULL;
		hr = pD2DRenderTarget->CreateBitmapBrush(pD2DBitmap, &pD2DBitmapBrush);
		if (FAILED(hr))
			return hr;
		m_pD2DBitmapBrush[pD2DRenderTarget] = pD2DBitmapBrush;
	}
	*ppBrush = m_pD2DBitmapBrush[pD2DRenderTarget];
	
	return S_OK;
}

HRESULT CDXResource::ClearD2DBitmapCache(ID2D1RenderTarget* pRenderTarget)
{
	for (std::map<ID2D1RenderTarget*, ID2D1Bitmap*>::iterator iter = m_pD2DBitmap.begin(); iter != m_pD2DBitmap.end(); iter++)
	{
		SAFE_RELEASE(iter->second);
	}
	m_pD2DBitmap.clear();
	return S_OK;

}
HRESULT CDXResource::ClearD2DBitmapBrushCache(ID2D1RenderTarget* pRenderTarget)
{
	for (std::map<ID2D1RenderTarget*, ID2D1BitmapBrush*>::iterator iter = m_pD2DBitmapBrush.begin(); iter != m_pD2DBitmapBrush.end(); iter++)
	{
		SAFE_RELEASE(iter->second);
	}
	m_pD2DBitmapBrush.clear();
	return S_OK;
}


HRESULT CDXResource::ClearColor(FLOAT color[4])
{
	if (m_pDevice == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3D11RenderTargetView* pRTView = NULL;
	hr = GetRenderTargetView(NULL, &pRTView);
	if (FAILED(hr))
		return hr;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	pContext->ClearRenderTargetView(pRTView, color);
	return S_OK;
}



CDXRenderResourceLocker::CDXRenderResourceLocker()
{
	m_bDrawCmdQueue10Locked = FALSE;
	m_bDrawCmdQueue11Locked = FALSE;
}
CDXRenderResourceLocker::~CDXRenderResourceLocker()
{
	UnLockAndClearDrawCmdResource10();
	UnLockAndClearDrawCmdResource11();
}

HRESULT CDXRenderResourceLocker::_PushDrawCmdResource10(CDXResource* pResource)
{
	if (pResource == NULL || m_bDrawCmdQueue10Locked)
		return E_FAIL;
	m_DrawCmdResourceQueue10.push_back(pResource);
	SAFE_ADDREF(pResource);
	return S_OK;
}
HRESULT CDXRenderResourceLocker::_PushAndLockDrawCmdResource10(CDXResource* pResource)
{
	if (pResource == NULL || m_bDrawCmdQueue10Locked)
		return E_FAIL;
	m_DrawCmdResourceQueue10.push_back(pResource);
	SAFE_ADDREF(pResource);
	pResource->KeyMutex10Acquire();
	return S_OK;
}
HRESULT CDXRenderResourceLocker::LockDrawCmdResource10()
{
	m_bDrawCmdQueue10Locked= TRUE;
	for (UINT i =0; i < m_DrawCmdResourceQueue10.size(); i++)
	{
		m_DrawCmdResourceQueue10[i]->KeyMutex10Acquire();
	}
	return S_OK;
}
HRESULT CDXRenderResourceLocker::UnLockAndClearDrawCmdResource10()
{
	for (UINT i =0; i < m_DrawCmdResourceQueue10.size(); i++)
	{
		m_DrawCmdResourceQueue10[i]->KeyMutex10Release();
		SAFE_RELEASE(m_DrawCmdResourceQueue10[i]);
	}
	m_DrawCmdResourceQueue10.clear();
	m_bDrawCmdQueue10Locked = FALSE;
	return S_OK;
}

HRESULT CDXRenderResourceLocker::_PushDrawCmdResource11(CDXResource* pResource)
{
	if (pResource == NULL || m_bDrawCmdQueue11Locked)
		return E_FAIL;
	m_DrawCmdResourceQueue11.push_back(pResource);
	SAFE_ADDREF(pResource);
	return S_OK;
}
HRESULT CDXRenderResourceLocker::_PushAndLockDrawCmdResource11(CDXResource* pResource)
{
	if (pResource == NULL || m_bDrawCmdQueue11Locked)
		return E_FAIL;
	m_DrawCmdResourceQueue11.push_back(pResource);
	SAFE_ADDREF(pResource);
	pResource->KeyMutex11Acquire();
	return S_OK;
}
HRESULT CDXRenderResourceLocker::LockDrawCmdResource11()
{
	m_bDrawCmdQueue11Locked= TRUE;
	for (UINT i =0; i < m_DrawCmdResourceQueue11.size(); i++)
	{
		m_DrawCmdResourceQueue11[i]->KeyMutex11Acquire();
	}
	return S_OK;
}
HRESULT CDXRenderResourceLocker::UnLockAndClearDrawCmdResource11()
{
	for (UINT i =0; i < m_DrawCmdResourceQueue11.size(); i++)
	{
		m_DrawCmdResourceQueue11[i]->KeyMutex11Release();
		SAFE_RELEASE(m_DrawCmdResourceQueue11[i]);
	}
	m_DrawCmdResourceQueue11.clear();
	m_bDrawCmdQueue11Locked = FALSE;
	return S_OK;
}
